home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr46 / vfwdk.zip / VFWSDK.ZIP / SAMPLES / BRAVADO / YUV.C < prev   
C/C++ Source or Header  |  1993-01-31  |  9KB  |  294 lines

  1. /****************************************************************************
  2.  *
  3.  *   yuv.c
  4.  * 
  5.  *   YUV to RGB conversion routines
  6.  *
  7.  *   Microsoft Video for Windows Sample Capture Driver
  8.  *   Chips & Technologies 9001 based frame grabbers.
  9.  *
  10.  *   Copyright (c) 1992-1993 Microsoft Corporation.  All Rights Reserved.
  11.  *
  12.  *    You have a royalty-free right to use, modify, reproduce and 
  13.  *    distribute the Sample Files (and/or any modified version) in 
  14.  *    any way you find useful, provided that you agree that 
  15.  *    Microsoft has no warranty obligations or liability for any 
  16.  *    Sample Application Files which are modified. 
  17.  *
  18.  ***************************************************************************/
  19.  
  20. #define NOMINMAX
  21. #include <windows.h>
  22. #include <mmsystem.h>
  23. #include <msvideo.h>
  24. #include <msviddrv.h>
  25. #include "ct.h"
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29.  
  30. // The Y component of the Phillips front end produces values
  31. // between 7 and 115 for a nominal signal.
  32. // The following table converts this range into 0 to 255
  33. // using a 5 bit lookup.
  34.  
  35. unsigned char map5to8[] = {
  36.    0,    0,   9,  19,  29,  39,  48,  58,
  37.    68,  78,  87,  97,  107, 117, 127, 136,
  38.    146, 156, 166, 175, 185, 195, 205, 214,
  39.    224, 234, 244, 255, 255, 255, 255, 255
  40. };
  41.  
  42.  
  43.  
  44.  
  45. /***************************************************************
  46. Convert a single line of unpacked 4:1:1 YUV data to RGB data.
  47. R = V * 179/127 + Y
  48. B = U * 226/127 + Y
  49. G = 1.706*Y + .509*R +.194*B
  50. Note: This routine is the same as above, but does not interpolate (JAYBO)
  51.  
  52. Parameters:    lpYUVBuf
  53.         Pointer to the YUV source buffer
  54.         lpRGBBuf
  55.         Pointer to the RGB destination buffer
  56.         nLineLen (<=1048)
  57.         Length of the YUV line in pixels
  58.         nBitsPerPix (16, 24, 32)
  59.         Number of bits per pixel in RGB data
  60. Returns:    None
  61. ***************************************************************/
  62. void FAR PASCAL CT_YUV2RGBNoInterp(BYTE huge *lpYUVBuf, BYTE huge *lpRGBBuf, 
  63.         int nLineLen, int nBitsPerPix)
  64. {
  65.     int i, j, k;
  66.     long inindx, outindx;
  67.     unsigned char rComp,gComp,bComp;
  68.     unsigned char Ypix[4];
  69.     char U, V;
  70.     int ScaledU, ScaledV;
  71.     int huge * lpnYUVBuf;                    
  72.     unsigned char huge *lpbRGBBuf;
  73.  
  74.     lpnYUVBuf=(int huge *)lpYUVBuf;
  75.     lpbRGBBuf=(char huge *)lpRGBBuf;
  76.     inindx = outindx = 0L;
  77.  
  78.     for (i=0;i<nLineLen;i+=4) {
  79.         /* Get 4 pixels, masking the Luma lsbs (only 7 bits were saved) */
  80.  
  81.         /* Note: this routine now masks each component to 5 bits.       */
  82.         /* This gives better conversion results to RGB.                 */
  83.  
  84.         k = *lpnYUVBuf++;
  85.         Ypix[0]= map5to8[(k & 0xf8) >> 3];
  86.         U = (char) ((k & 0xc000) >> 8); // (8 + 2*0)
  87.         V = (char) ((k & 0x3000) >> 6); // (6 + 2*0)
  88.  
  89.         k = *lpnYUVBuf++;
  90.         Ypix[1]= map5to8[(k & 0xf8) >> 3];
  91.         U |= (k & 0xc000) >> 10; // (8 + 2*1)
  92.         V |= (k & 0x3000) >> 8;  // (6 + 2*1)
  93.  
  94.         k = *lpnYUVBuf++;
  95.         Ypix[2]= map5to8[(k & 0xf8) >> 3];
  96.         U |= (k & 0xc000) >> 12; // (8 + 2*2)
  97.         V |= (k & 0x3000) >> 10; // (6 + 2*2)
  98.  
  99.         k = *lpnYUVBuf++;
  100.         Ypix[3]= map5to8[(k & 0xf8) >> 3];
  101.         U |= (k & 0xc000) >> 14; // (8 + 2*3)
  102.         V |= (k & 0x3000) >> 12; // (6 + 2*3)
  103.  
  104.         /* Only the top 7 Chroma bits are valid, so.... */
  105.         U &= 0xf8;
  106.         V &= 0xf8;
  107.  
  108.         /* Now scale and form the RGB values */
  109.         ScaledU =  MulDiv((int)U,462,256);  // 229/127 = 1.803
  110.         ScaledV =  MulDiv((int)V,361,256);  // 179/127 = 1.409
  111.         for (j=0; j<4; ++j) {
  112.             rComp = (unsigned char) max(0, 
  113.                         min(255, (int) (ScaledV + (int)Ypix[j])));
  114.             bComp = (unsigned char) max(0, 
  115.                         min(255, (int) (ScaledU + (int)Ypix[j])));
  116.             // G = 1.706 * Y - 0.5094 * R - 0.1942 * B 
  117.             gComp = (unsigned char) max(0, 
  118.                         min(255, (int) ((Ypix[j] * 1747L - rComp * 522L - bComp * 199L) >> 10)));
  119.  
  120.             if (nBitsPerPix >= 24) {
  121.                 *lpbRGBBuf++=bComp;
  122.                 *lpbRGBBuf++=gComp;
  123.                 *lpbRGBBuf++=rComp;
  124.             }
  125.             else {
  126.                 bComp>>=3;
  127.                 gComp>>=3;
  128.                 rComp>>=3;
  129.                 *lpbRGBBuf++=(unsigned char) (bComp | ((gComp & 0x07) << 5));
  130.                 *lpbRGBBuf++=(unsigned char) ((rComp << 2) | ((gComp & 0x18) >> 3));
  131.             }
  132.         }
  133.     }
  134. }
  135.  
  136.  
  137.  
  138. #ifdef NOT_USED
  139. /***************************************************************
  140. Convert a single line of RGB data to unpacked 4:1:1 YUV.
  141. Y = .299*R + .587*G + .114*B
  142. V = (R-Y) * 127/179
  143. U = (B-Y) * 127/226
  144. Note: The low bit of each YUV componant is dropped
  145.       This routine has been updated to handle more than a single line.
  146.  
  147. Parameters:    lpRGBBuf
  148.         Pointer to the RGB source buffer
  149.         lpYUVBuf
  150.         Pointer to the YUV destination buffer
  151.         nLineLen (<=1048)
  152.         Length of the RGB line in pixels
  153.         nBitsPerPix (8, 16, 24, 32)
  154.         Number of bits per pixel in RGB data
  155. Returns:    None
  156. ***************************************************************/
  157. void FAR PASCAL CT_RGB2YUV(LPSTR lpRGBBuf, LPSTR lpYUVBuf, long nLineLen, int nBitsPerPix)
  158. {
  159.         int  j;
  160.     long i;
  161.     long inindx, outindx;
  162.     unsigned char rComp,gComp,bComp;
  163.     unsigned char Ypix[4];
  164.     char U, V;
  165.     int tmpU, tmpV;
  166.     static unsigned char cmask[]={0x60,0x18,0x06,0x01};
  167.     int huge *lpnYUVBuf;
  168.     char huge *lpbRGBBuf;
  169.  
  170.     lpnYUVBuf=(int huge *)lpYUVBuf;
  171.     lpbRGBBuf=(char huge *)lpRGBBuf;
  172.  
  173.     for (i=inindx=outindx=0;i<nLineLen;i+=4) {
  174.         for (j=tmpU=tmpV=0;j<4;++j) {
  175.             /* Get a RGB pixel (24, 32, or 16 bits) */
  176.             if (nBitsPerPix >= 24) {
  177.                 bComp=lpbRGBBuf[inindx++];
  178.                 gComp=lpbRGBBuf[inindx++];
  179.                 rComp=lpbRGBBuf[inindx++];
  180.                 if (nBitsPerPix > 24) inindx++;
  181.             }
  182.             else {
  183.                 bComp = lpbRGBBuf[inindx] & 0x1f;
  184.                 gComp = (lpbRGBBuf[inindx++] & 0xe0) >> 5;
  185.                 gComp |= ((lpbRGBBuf[inindx] & 0x03) << 3);
  186.                 rComp = (lpbRGBBuf[inindx++] & 0x7c) >> 2;
  187.                 bComp = map5to8[bComp];
  188.                 gComp = map5to8[gComp];
  189.                 rComp = map5to8[rComp];
  190.             }
  191.             
  192.             /* Calculate Lumas and running Chroma totals */
  193.             Ypix[j]= (gComp*587L)/1000
  194.                  + (rComp*299L)/1000 + (bComp*114L)/1000;
  195.             tmpU += (((int)bComp-(int)Ypix[j])*127L)/226;
  196.             tmpV += (((int)rComp-(int)Ypix[j])*127L)/179;
  197.         }
  198.  
  199.         /* Divide by four to get average, divide by 2 to drop LSB */
  200.         U = (tmpU/4)/2;
  201.         V = (tmpV/4)/2;
  202.  
  203.         /* Send the pixels out in unpacked format */
  204.         for (j=0; j<4; ++j) {
  205.             lpnYUVBuf[outindx]=Ypix[j] & 0xfe;
  206.             lpnYUVBuf[outindx] |= ((V & cmask[j]) << (7 + 2*j));
  207.             lpnYUVBuf[outindx++] |= ((U & cmask[j]) << (9 + 2*j));
  208.         }
  209.     }
  210. }
  211.  
  212.  
  213. /***************************************************************
  214. Convert a single line of unpacked 4:1:1 YUV data to RGB data.
  215. R = V * 179/127 + Y
  216. B = U * 226/127 + Y
  217. G = 1.706*Y + .509*R +.194*B
  218. Note: This routine has been updated to handle more than a single line.
  219.  
  220. Parameters:    lpYUVBuf
  221.         Pointer to the YUV source buffer
  222.         lpRGBBuf
  223.         Pointer to the RGB destination buffer
  224.         nLineLen (<=1048)
  225.         Length of the YUV line in pixels
  226.         nBitsPerPix (8, 16, 24, 32)
  227.         Number of bits per pixel in RGB data
  228. Returns:    None
  229. ***************************************************************/
  230. void FAR PASCAL CT_YUV2RGB(LPSTR lpYUVBuf, LPSTR lpRGBBuf, int nLineLen, int nBitsPerPix)
  231. {
  232.     int i, j;
  233.     long inindx, outindx;
  234.     unsigned char rComp,gComp,bComp;
  235.     unsigned char Ypix[4];
  236.     char U, V, lastU, lastV, Upix[4], Vpix[4];
  237.     int diffU, diffV;
  238.     int huge *lpnYUVBuf;
  239.     char huge *lpbRGBBuf;
  240.  
  241.     lpnYUVBuf=(int huge *)lpYUVBuf;
  242.     lpbRGBBuf=(char huge *)lpRGBBuf;
  243.  
  244.     for (i=inindx=outindx=0;i<nLineLen;i+=4) {
  245.         /* Get 4 pixels, masking the Luma lsbs (only 7 bits were saved) */
  246.         /* Gather the Chromas */
  247.         for (j=U=V=0;j<4;++j) {
  248.             Ypix[j]=(lpnYUVBuf[inindx] & 0xfe);
  249.             U |= (lpnYUVBuf[inindx] & 0xc000) >> (8 + 2*j);
  250.             V |= (lpnYUVBuf[inindx++] & 0x3000) >> (6 + 2*j);
  251.         }
  252.         /* Only the top 7 Chroma bits are valid, so.... */
  253.         U &= 0xfe;
  254.         V &= 0xfe;
  255.         /* First set? */
  256.         if (i==0) {
  257.             lastU=U;    /* Yes, no interp */
  258.             lastV=V;
  259.         }
  260.  
  261.         diffU = U-lastU;
  262.         diffV = V-lastV;
  263.         /* Now scale and form the RGB values */
  264.         /* Use linear interpolation to avoid blockiness */
  265.         for (j=0; j<4; ++j) {
  266.             Vpix[j] = lastV + (diffV * (j+1))/4;
  267.             Upix[j] = lastU + (diffU * (j+1))/4;
  268.  
  269.             rComp = max(0, min(255, (Vpix[j]*179L)/127 + (int)Ypix[j]));
  270.                 bComp = max(0, min(255, (Upix[j]*226L)/127 + (int)Ypix[j]));
  271.             gComp = max(0, min(255, ((int)Ypix[j] * 1706L)/1000 - ((rComp * 509L)/1000) - ((bComp * 194L)/1000)));
  272.  
  273.             if (nBitsPerPix >= 24) {
  274.                 lpbRGBBuf[outindx++]=bComp;
  275.                 lpbRGBBuf[outindx++]=gComp;
  276.                 lpbRGBBuf[outindx++]=rComp;
  277.             }
  278.             else {
  279.                 bComp>>=3;
  280.                 gComp>>=3;
  281.                 rComp>>=3;
  282.                 lpbRGBBuf[outindx++]=bComp | ((gComp & 0x07) << 5);
  283.                 lpbRGBBuf[outindx++]=(rComp << 2) | ((gComp & 0x18) >> 3);
  284.             }
  285.         }
  286.     /* Save last Chroma values for interpolation */
  287.     lastU=U;
  288.     lastV=V;
  289.     }
  290. }
  291.  
  292. #endif          // NOT_USED
  293.  
  294.